#include "com.h"
#include <QDebug>
#include <QDateTime>
#include <QThread>

Com::Com(QString port_name,int rate,QObject *parent) : QObject(parent)
{
	port.setPortName(port_name);
	port.setBaudRate(rate);
	port.setStopBits(QSerialPort::OneStop);
	port.setParity(QSerialPort::NoParity);

	con_sem = new QSemaphore(0);
}

Com::~Com()
{
	delete con_sem;
}

bool Com::open()
{
	if(port.open(QIODevice::ReadWrite)){
		qDebug()<<"Open serial port "<<port.portName()<<" successful";
		qDebug()<<"ThreadId:"<<QThread::currentThreadId()<<endl;
	}else{
		qDebug()<<"Open serial port "<<port.portName()<<" failed";
		return false;
	}

	QObject::connect(&port,&QSerialPort::readyRead,this,&Com::Read_Data);
	return true;
}

void Com::Read_Data()
{
	if(read_data_running == true){
		return;
	}
	read_data_running = true;
	QByteArray  buf;


	while(1){
		buf = port.readAll();
		if(buf.isEmpty()){
			goto exit;
		}

		QString str(buf);
		QByteArray line;


		receive_data += buf;

		while(1){
			int end = receive_data.indexOf("\n");
			if(end != -1){
				QDateTime time = QDateTime::currentDateTime();
				QString ctime = time.toString("[yyyy-MM-dd hh:mm:ss.zzz] ");
				QString sline;
				//ui->textEdit->insertPlainText(ctime);
				emit recv_data(ctime);
				sline.append(ctime);
				line = receive_data.mid(0,end);

				if(line[line.length()-2] == '\r'){
					line.remove(line.length()-2,1);
				}
				receive_data = receive_data.mid(end+1);

				while(1){
					int st = line.indexOf("\033[");
					if(st != -1){
						QByteArray s1 = line.mid(0,st);
						sline.append(s1);

						emit recv_data(s1);
						//ui->textEdit->insertPlainText(s1);
						int e = line.indexOf("m",st);
						QByteArray colorp = line.mid(st+2,e-2);

						int e2 = colorp.indexOf(";");
						if(e2 != -1){
							QByteArray colorp1 = colorp.mid(0,e2);
							//set_consolecolor(colorp1.toInt());
							emit style_change(colorp1.toInt());

							colorp = colorp.mid(e2+1);
							//set_consolecolor(colorp.toInt());
							emit style_change(colorp.toInt());
						}else{
							//set_consolecolor(colorp.toInt());
							emit style_change(colorp.toInt());
						}

						line = line.mid(e+1);

					}else{
						sline.append(line);
						emit recv_data(line);
						//ui->textEdit->insertPlainText(line);
						//ui->textEdit->moveCursor(QTextCursor::End);
						break;
					}
				}
				check_line(sline);
			}else{
				break;
			}
		}
	}

exit:
	read_data_running = false;
}

void Com::check_line(QString line)
{
	int i;
	rule_mutex.lock();
	for(i = 0; i < checklist.size(); i++){
		int pos = checklist[i]->indexIn(line);
		if(pos != -1){
			rule_result = checklist[i]->cap();
			con_sem->release();
			break;
		}
	}
	rule_mutex.unlock();
}

void *Com::add_check_rule(QString rule)
{
	QRegExp *rx = new QRegExp(rule);
	checklist.append(rx);

	return rx;
}

void Com::delete_rule(void *rule)
{
	checklist.removeOne((QRegExp*)rule);
}

QString Com::wait_string(QString str, int timeout_ms)
{
	rule_mutex.lock();
	void *rule = add_check_rule(str);
	rule_mutex.unlock();
	int ret = con_sem->tryAcquire(1, timeout_ms);
	if(!ret){
		return NULL;
	}
	rule_mutex.lock();
	delete_rule(rule);
	rule_mutex.unlock();
	return rule_result;
}

int Com::send(QByteArray cmd)
{
	char *buf = cmd.data();
	int ret = port.write(buf,cmd.length());
	port.flush();
	return ret;
}

